package com.helloscala.web
package snippet

import scala.xml.NodeSeq

import net.liftweb.common.{Empty, Failure, Loggable, Full}
import net.liftweb.http.{S, Templates, SHtml, DispatchSnippet}
import net.liftweb.util.Helpers._
import net.liftweb.http.js.{JsCmd, JsCmds}

import com.helloscala.model.{MUser, MMicroChatReply, MMicroChat}
import com.helloscala.service.MicroChatManager
import com.helloscala.helper.{HelloHelpers, MicroChat}

object MicroChatSnippet extends DispatchSnippet with Loggable {
  def dispatch = {
    case "global" => global
    case "replyDetail" => replyDetail
    case "replies" => replies
    case "replyForm" => replyForm
  }

  def global(nodeSeq: NodeSeq): NodeSeq = {
    val sel =
      W.theAccount.is match {
        case Full(account) =>
          val contentId = nextFuncName
          var content = ""

          "@content [id]" #> contentId &
            "@content" #> SHtml.text(content, content = _) &
            "@submit" #> SHtml.hidden(() => {
              MMicroChat.insert(account.id, content) match {
                case Full(mc) =>
                  MicroChatManager ! MicroChat(mc)

                case Failure(msg, e, _) =>
                  val errorMsg = e openOr msg
                  logger.error(errorMsg)

                case _ =>
                  logger.error("发布微聊失败: " + content)
              }
              $("#" + contentId).value("").cmd
            })

        case _ =>
          ".panel-body *" #> <a href={W.hrefGotoPage("/c/sign_in")}>登录发布微聊</a>
      }

    val cssSel =
      sel &
        "#micro-chat-list .list-group-item" #> MicroChatManager.microChats.map(MicroChatHelpers.chatLi _)

    cssSel(nodeSeq)
  }

  def replyDetail(nodeSeq: NodeSeq): NodeSeq = {
    val cssSel =
      for (mc <- W.reqMicroChat.is)
      yield {
        ".breadcrumb" #> (
          "@account *" #> S.param("user_id").flatMap(MUser.findNickById).openOr(mc.creator) &
            "@account [href]" #> W.hrefUser(mc.creator)
          ) &
          ".user-avatar" #> (
            "a [href]" #> W.hrefUser(mc.creator)
            ) &
          ".user-info" #> (
            "@content *" #> mc.content &
              "@time *" #> HelloHelpers.timeDescription(mc.created_at)
            )
      }

    cssSel match {
      case Full(sel) =>
        sel(nodeSeq)

      case Failure(msg, e, _) =>
        e.foreach(_.printStackTrace)
        val errorMsg = e.map(_.getLocalizedMessage) openOr msg
        logger.error(errorMsg)

        <h1 class="text-danger">
          {errorMsg}
        </h1>

      case Empty =>
        NodeSeq.Empty
    }
  }

  def replies(nodeSeq: NodeSeq): NodeSeq = {
    val curPage = H.param("cur_page", 1)
    val limit = H.param("limit", H.defaultLimit)

    val cssSel =
      for (mc <- W.reqMicroChat.is)
      yield {
        val pagination = MMicroChatReply.pagination(curPage, limit, microChatId = Some(mc.id))

        "@reply-size *" #> s"共收到 ${pagination.total} 回复" &
          ".list-group-item" #> pagination.page.map(mcr => replyLi(mcr)) &
          ".pagination" #> pagination.pagination("")
      }

    cssSel map (_ apply nodeSeq) openOr NodeSeq.Empty
  }

  def replyForm(nodeSeq: NodeSeq): NodeSeq = {
    var replyText = ""

    def funcSubmit(microChatId: String, creator: String): JsCmd =
      MMicroChatReply.insert(microChatId, creator, replyText) match {
        case Full(mcr) =>
          $("#micro-replies").append(replyLi(mcr)).cmd &
            $("#micro-chat-reply-text").value("").cmd

        case _ =>
          JsCmds.Noop
      }

    val cssSel =
      for {
        account <- W.theAccount.is
        mc <- W.reqMicroChat.is
      } yield
        "#micro-chat-reply-text" #> SHtml.textarea(replyText, replyText = _) &
          "@submit" #> SHtml.hidden(() => funcSubmit(mc.id, account.id))

    cssSel.map(_ apply nodeSeq) openOr NodeSeq.Empty
  }

  private def replyLi(reply: MMicroChatReply): NodeSeq = {
    val cssSel =
      ".user-avatar" #> (
        "a [href]" #> W.hrefUser(reply.creator)
        ) &
        ".user-info" #> (
          "@content *" #> reply.content &
            "@time *" #> HelloHelpers.timeDescription(reply.created_at)
          )

    cssSel(nodeDetailLi)
  }

  def nodeDetailLi = Templates(List("p", "micro_chat", "_detail_li")).openOrThrowException("/p/micro_chat/_detail_li not found!!!")
}
